#include "RL_RS485_FSFX.h"

// CRC16校验实现（适用于前6字节数据）
uint16_t RS485_FSFX::crc16(const byte* data, uint8_t len) {
    uint16_t crc = 0xFFFF;  // 初始值
    for (uint8_t i = 0; i < len; i++) {
        crc ^= data[i];     // 与当前字节异或
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x0001) {  // 最低位为1
                crc = (crc >> 1) ^ 0xA001;  // 右移并异或多项式
            } else {
                crc >>= 1;  // 右移
            }
        }
    }
    return crc;
}

void RS485_FSFX::requestfs() {
    if (_debugMode) Serial.println("[LOG] 发送风速请求指令...");
    this->write(fs_request, sizeof(fs_request));
}

float RS485_FSFX::readfs() {
    delay(100);  // 等待设备响应
    this->flush();  // 清空接收缓冲区
    int bytesRead = 0;
    unsigned long startTime = millis();

    if (_debugMode) Serial.println("[LOG] 开始读取风速数据...");
    // 读取8字节数据（带超时处理）
    while (bytesRead < 7 && (millis() - startTime) < _timeout) {
        if (this->available()) {
            bytesRead += this->readBytes(&fs_buf[bytesRead], 7 - bytesRead);
        }
    }
	

    // 打印读取到的字节数
    if (_debugMode) {
        Serial.print("[LOG] 风速数据读取完成，共读取 ");
        Serial.print(bytesRead);
        Serial.println(" 字节");
    }

    // 检查是否读取到完整的7字节
    if (bytesRead != 7) {
        if (_debugMode) Serial.println("[ERROR] 风速数据读取超时或不完整");
        return -1.0f;  // 超时或数据不完整
    }

    // 打印读取到的原始数据
    if (_debugMode) {
        Serial.print("[LOG] 风速原始数据：");
        for (int i = 0; i < 7; i++) {
            Serial.print("0x");
            if (fs_buf[i] < 0x10) Serial.print("0");
            Serial.print(fs_buf[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }

    // 校验CRC
    uint16_t calculatedCrc = crc16(fs_buf, 5);  // 前6字节计算CRC
    uint8_t receivedCrcLow = fs_buf[5];         // 接收的CRC低位（第5字节）
    uint8_t receivedCrcHigh = fs_buf[6];        // 接收的CRC高位（第6字节）
    uint16_t receivedCrc = (receivedCrcHigh << 8) | receivedCrcLow;

    // 打印CRC校验信息
    if (_debugMode) {
        Serial.print("[LOG] 计算的CRC：0x");
        Serial.print(calculatedCrc, HEX);
        Serial.print("，接收的CRC：0x");
        Serial.println(receivedCrc, HEX);
    }

    if (calculatedCrc != receivedCrc) {
        if (_debugMode) Serial.println("[ERROR] 风速CRC校验失败");
        return -2.0f;  // CRC校验失败
    }

    // 计算风速值并打印
    float fsValue = (fs_buf[3] * 256 + fs_buf[4]) * 0.1f;
    if (_debugMode) {
        Serial.print("[LOG] 风速值计算完成：");
        Serial.println(fsValue);
    }

    return fsValue;
}

int RS485_FSFX::readfs_level() {
    float fs = readfs();
    if (fs < 0) {  // 读取失败（超时或CRC错误）
        if (_debugMode) Serial.println("[ERROR] 风速等级计算失败（底层读取错误）");
        return -1;
    }

    // 风速等级判断
    int level;
    if (fs < 0.3) level = 0;
    else if (fs < 1.6) level = 1;
    else if (fs < 3.4) level = 2;
    else if (fs < 5.5) level = 3;
    else if (fs < 8.0) level = 4;
    else if (fs < 10.8) level = 5;
    else if (fs < 13.9) level = 6;
    else if (fs < 17.2) level = 7;
    else if (fs < 20.8) level = 8;
    else if (fs < 24.5) level = 9;
    else if (fs < 28.5) level = 10;
    else if (fs < 32.7) level = 11;
    else if (fs < 37.0) level = 12;
    else if (fs < 41.5) level = 13;
    else if (fs < 46.2) level = 14;
    else if (fs < 51.0) level = 15;
    else if (fs < 56.1) level = 16;
    else level = 17;

    if (_debugMode) {
        Serial.print("[LOG] 风速等级：");
        Serial.println(level);
    }
    return level;
}

void RS485_FSFX::requestfx() {
    if (_debugMode) Serial.println("[LOG] 发送风向请求指令...");
    this->write(fx_request, sizeof(fx_request));
}

float RS485_FSFX::readfx() {
    delay(100);  // 等待设备响应
    this->flush();  // 清空接收缓冲区
    int bytesRead = 0;
    unsigned long startTime = millis();

    if (_debugMode) Serial.println("[LOG] 开始读取风向数据...");
    // 读取9字节数据（带超时处理）
    while (bytesRead < 9 && (millis() - startTime) < _timeout) {
        if (this->available()) {
            bytesRead += this->readBytes(&fx_buf[bytesRead], 9 - bytesRead);
        }
    }
	
    // 打印读取到的字节数
    if (_debugMode) {
        Serial.print("[LOG] 风向数据读取完成，共读取 ");
        Serial.print(bytesRead);
        Serial.println(" 字节");
    }

    // 检查是否读取到完整的8字节
    if (bytesRead != 9) {
        if (_debugMode) Serial.println("[ERROR] 风向数据读取超时或不完整");
        return -1.0f;  // 超时或数据不完整
    }

    // 打印读取到的原始数据
    if (_debugMode) {
        Serial.print("[LOG] 风向原始数据：");
        for (int i = 0; i < 9; i++) {
            Serial.print("0x");
            if (fx_buf[i] < 0x10) Serial.print("0");
            Serial.print(fx_buf[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }

    // 校验CRC
    uint16_t calculatedCrc = crc16(fx_buf, 7);  // 前6字节计算CRC
    uint8_t receivedCrcLow = fx_buf[7];         // 接收的CRC低位（第7字节）
    uint8_t receivedCrcHigh = fx_buf[8];        // 接收的CRC高位（第8字节）
    uint16_t receivedCrc = (receivedCrcHigh << 8) | receivedCrcLow;

    // 打印CRC校验信息
    if (_debugMode) {
        Serial.print("[LOG] 计算的CRC：0x");
        Serial.print(calculatedCrc, HEX);
        Serial.print("，接收的CRC：0x");
        Serial.println(receivedCrc, HEX);
    }

    if (calculatedCrc != receivedCrc) {
        if (_debugMode) Serial.println("[ERROR] 风向CRC校验失败");
        return -2.0f;  // CRC校验失败
    }

    // 计算风向值并打印
    float fxValue = (fx_buf[3] * 256 + fx_buf[4]) * 0.1f;
    if (_debugMode) {
        Serial.print("[LOG] 风向值计算完成：");
        Serial.println(fxValue);
    }

    return fxValue;
}

bool RS485_FSFX::readfx_dir(int dir) {
    float fx = readfx();
    if (fx < 0) {  // 读取失败（超时或CRC错误）
        if (_debugMode) Serial.println("[ERROR] 风向方向判断失败（底层读取错误）");
        return false;
    }

    // 风向判断
    bool result;
    if (dir == 0) {
        result = (fx < 22.5 || (fx >= 337.5 && fx <= 360.0));
    } else if (dir == 1) {
        result = (fx >= 22.5 && fx < 67.5);
    } else if (dir == 2) {
        result = (fx >= 67.5 && fx < 112.5);
    } else if (dir == 3) {
        result = (fx >= 112.5 && fx < 157.5);
    } else if (dir == 4) {
        result = (fx >= 157.5 && fx < 202.5);
    } else if (dir == 5) {
        result = (fx >= 202.5 && fx < 247.5);
    } else if (dir == 6) {
        result = (fx >= 247.5 && fx < 292.5);
    } else if (dir == 7) {
        result = (fx >= 292.5 && fx < 337.5);
    } else {
        if (_debugMode) Serial.println("[ERROR] 无效的风向方向参数");
        return false;
    }

    if (_debugMode) {
        Serial.print("[LOG] 风向匹配结果（方向 ");
        Serial.print(dir);
        Serial.print("）：");
        Serial.println(result ? "匹配" : "不匹配");
    }
    return result;
}